#include "RdfParser.h"
#include <redland.h>
#include <raptor2.h>
#include <rasqal.h>
#define RASQAL_INTERNAL
#define RAPTOR_INTERNAL
#include <rasqal_internal.h>
#include <raptor_internal.h>
#include "RdfStore.h"
#include <set>
#include <QtCore>



void handle_triple(void* user_data, raptor_statement* triple);
std::string raptor_statement_get_subject(const raptor_statement* statement);
std::string raptor_statement_get_predicate(const raptor_statement* statement);
std::string raptor_statement_get_object(const raptor_statement* statement);

QFile file[28];
int counter=0;


RdfParser::RdfParser(const char* fileName){
    raptor_world_pt=NULL;
	raptor_parser_pt=NULL;
	raptor_uri_string_pt=NULL;
	raptor_uri_pt=NULL;
	raptor_base_uri_pt=NULL;
	std::string node_identifier;
	for(int i=0;i<27;i++){
		std::ostringstream nodeID_s[3];
		int nodeID_i[3];
		nodeID_i[2] = i % 3;
		nodeID_i[1] = (i/3) % 3;
		nodeID_i[0] = (i/9) % 3;
	   	for(int index=0; index<3; index++)
	    		nodeID_s[index] << nodeID_i[index];
	    node_identifier = "toSendFile/semantic_node_" + nodeID_s[0].str() + "_" + nodeID_s[1].str() + "_" + nodeID_s[2].str() +".rdf";
		file[i].setFileName(node_identifier.c_str());
		if(!file[i].open(QIODevice::WriteOnly)){
			std::cout << "error creating file[" << i << "]"<<std::endl;
		}
	}
	file[27].setFileName("toSendFile/semantic_all.rdf");
	file[27].open(QIODevice::WriteOnly);

	raptor_world_pt = raptor_new_world(); //初始化raptor的变量world，为raptor_world分配资源
	 /*
	  * raptor执行解释文本的代码段
	  */
	raptor_parser_pt = raptor_new_parser(raptor_world_pt, "rdfxml"); //解释器可以为 “rdfxml”
	raptor_parser_set_statement_handler(raptor_parser_pt, NULL,handle_triple );
	raptor_uri_string_pt = raptor_uri_filename_to_uri_string((char*)fileName);
	raptor_uri_pt = raptor_new_uri(raptor_world_pt, raptor_uri_string_pt);
	raptor_base_uri_pt = raptor_uri_copy(raptor_uri_pt);
	raptor_parser_parse_file(raptor_parser_pt, raptor_uri_pt, raptor_base_uri_pt); //开始执行解释文本,结果存在semantic_element_string中
}


RdfParser::~RdfParser(){
	/*
	 * 释放raptor指针
	 */
//	for(int i=0;i<28;i++){
//		delete store[i];
//	}
	std::cout << "closing files " << std::endl;
	for(int i=0;i<28;i++){
		file[i].close();
	}
	std::cout << "deleting aptor_parser_pt" << std::endl;
	raptor_free_parser(raptor_parser_pt);
	if(raptor_base_uri_pt){
		std::cout << "deleting raptor_base_uri_pt" << std::endl;
		raptor_free_uri(raptor_base_uri_pt);
	}
	if(raptor_uri_pt){
		std::cout << "deleting raptor_uri_pt" << std::endl;
		raptor_free_uri(raptor_uri_pt);
	}
	if(raptor_uri_string_pt){
		std::cout << "deleting raptor_uri_string_pt" << std::endl;
		raptor_free_memory(raptor_uri_string_pt);
	}
	std::cout << "deleting raptor_world_pt" << std::endl;
	raptor_free_world(raptor_world_pt);
}


void handle_triple(void* user_data, raptor_statement* triple){
	std::string subject,predicate,object;
	QString subjectQS;
	QString predicateQS;
	QString objectQS;
	QByteArray subjectQA;
	QByteArray predicateQA;
	QByteArray objectQA;
	short s_Co;
	short p_Co;
	short o_Co;
	short s_p_Co;
	short s_o_Co;
	short p_o_Co;
	short pos[7];
	std::set<short> pos_set;
	std::string semantic_element_string;
	QString semantic_element_qstring;
	QByteArray semantic_element_qa;

	/*
	 * 此处提取出语义元素，转为HASH码，并发送出去。
	 */
	subject = raptor_statement_get_subject(triple);
	predicate = raptor_statement_get_predicate(triple);
	object = raptor_statement_get_object(triple);

	subjectQS = QString::fromLocal8Bit(subject.c_str());
	subjectQA = QCryptographicHash::hash(subjectQS.toAscii(),QCryptographicHash::Sha1 );

	predicateQS = QString::fromLocal8Bit(predicate.c_str());
	predicateQA = QCryptographicHash::hash(predicateQS.toAscii(),QCryptographicHash::Sha1 );

	objectQS = QString::fromLocal8Bit(object.c_str());
	objectQA = QCryptographicHash::hash(objectQS.toAscii(),QCryptographicHash::Sha1 );

	s_Co = (uint)subjectQA[0] % 3;   //S
	p_Co = (uint)predicateQA[0] % 3; //p
	o_Co = (uint)objectQA[0] % 3; 	//O

	s_p_Co = (s_Co + p_Co) % 3;		//s+p
	s_o_Co = (s_Co + o_Co) % 3;		//s+o
	p_o_Co = (p_Co + o_Co) % 3;		//p+o


	//=======================================Test the new coordinate============================================//

	std::string subject_y,predicate_y,object_y;
	std::string subject_z,predicate_z,object_z;
	QString subjectQS_y;
	QString predicateQS_y;
	QString objectQS_y;
	QByteArray subjectQA_y;
	QByteArray predicateQA_y;
	QByteArray objectQA_y;
	QString subjectQS_z;
	QString predicateQS_z;
	QString objectQS_z;
	QByteArray subjectQA_z;
	QByteArray predicateQA_z;
	QByteArray objectQA_z;
	short s_Co_y;
	short p_Co_y;
	short o_Co_y;
	short s_Co_z;
	short p_Co_z;
	short o_Co_z;

	subject_y = subject+' ';
	predicate_y = predicate+' ';
	object_y = object+' ';
	subject_z = subject_y+' ';
	predicate_z = predicate_y+' ';
	object_z = object_y+' ';

	subjectQS_y = QString::fromLocal8Bit(subject_y.c_str());
	subjectQA_y = QCryptographicHash::hash(subjectQS_y.toAscii(),QCryptographicHash::Sha1 );

	predicateQS_y = QString::fromLocal8Bit(predicate_y.c_str());
	predicateQA_y = QCryptographicHash::hash(predicateQS_y.toAscii(),QCryptographicHash::Sha1 );

	objectQS_y = QString::fromLocal8Bit(object_y.c_str());
	objectQA_y = QCryptographicHash::hash(objectQS_y.toAscii(),QCryptographicHash::Sha1 );

	subjectQS_z = QString::fromLocal8Bit(subject_z.c_str());
	subjectQA_z = QCryptographicHash::hash(subjectQS_z.toAscii(),QCryptographicHash::Sha1 );

	predicateQS_z = QString::fromLocal8Bit(predicate_z.c_str());
	predicateQA_z = QCryptographicHash::hash(predicateQS_z.toAscii(),QCryptographicHash::Sha1 );

	objectQS_z= QString::fromLocal8Bit(object_z.c_str());
	objectQA_z = QCryptographicHash::hash(objectQS_z.toAscii(),QCryptographicHash::Sha1 );

	s_Co_y = (uint)subjectQA_y[0] % 3;   //S
	p_Co_y = (uint)predicateQA_y[0] % 3; //p
	o_Co_y = (uint)objectQA_y[0] % 3; 	//O

	s_Co_z = (uint)subjectQA_z[0] % 3;   //S
	p_Co_z = (uint)predicateQA_z[0] % 3; //p
	o_Co_z = (uint)objectQA_z[0] % 3; 	//O


	s_p_Co = (s_Co_z + p_Co_z) % 3;		//s+p
	s_o_Co = (s_Co_y + o_Co_y) % 3;		//s+o
	p_o_Co = (p_Co + o_Co) % 3;		//p+o






	//=======================================End of The Test ===================================================//

	pos[0]=s_Co *9 + p_Co_y*3 + o_Co_z;  //[s,p,o]
	pos[1]=p_o_Co*9 + p_Co_y*3 + o_Co_z; //[p+o,p,o]
	pos[2]=s_Co *9 + s_o_Co*3 + o_Co_z; //[s,s+o,o]
	pos[3]=s_Co *9 + p_Co_z*3 + s_p_Co; //[s,p,s+p]
	pos[4]=s_Co *9 + s_Co_y*3 + s_Co_z; // [s,s,s]
	pos[5]=p_Co *9 + p_Co_y*3 + p_Co_z; // [p,p,p]
	pos[6]=o_Co *9 + o_Co_y*3 + o_Co_z; // [o,o,o]
	pos[7]=27;

	for(int j=0;j<8; j++){
		pos_set.insert(pos[j]);
	}
	semantic_element_string= subject + " " + predicate + " " + object+"\n";
	semantic_element_qstring= subjectQS+ " " + predicateQS + " " + objectQS + "\n";
	semantic_element_qa = semantic_element_qstring.toAscii();
	std::cout << semantic_element_string << std::endl;
	std::cout << "mapping to the coordinate: " <<  "[" << s_Co <<" , " << p_Co_y << " , " << o_Co_z << "] ";
	std::cout << "[" << p_o_Co <<" , " << p_Co_y << " , " << o_Co_z << "] " ;
	std::cout << "[" << s_Co <<" , " << s_o_Co << " , " << o_Co_z << "] " ;
	std::cout << "[" << s_Co <<" , " << p_Co_y << " , " << s_p_Co << "] " ;
	std::cout << "[" << s_Co <<" , " << s_Co_y << " , " << s_Co_z << "] " ;
	std::cout << "[" << p_Co <<" , " << p_Co_y << " , " << p_Co_z << "] " ;
	std::cout << "[" << o_Co <<" , " << o_Co_y << " , " << o_Co_z << "] "  << std::endl;
	for(std::set<short>::iterator i=pos_set.begin();i!=pos_set.end();i++){
//		std::cout << "Store in [" << *i << "]" << std::endl;
//		store[*i]->store_triple(subject.c_str(),predicate.c_str(),object.c_str());
		file[*i].write(semantic_element_qa);
	}
	counter++;
//	std::cout << "Store the " << counter << " element OK!" << std::endl;

}


std::string raptor_statement_get_subject(const raptor_statement* statement){
	std::string data;
	if (!statement->subject) {
		data+=" NULL ";
	} else {
		if (statement->subject->type == RAPTOR_TERM_TYPE_BLANK) {
			data+=(const char*) statement->subject->value.blank.string;
		} else {
			data+=(const char*) raptor_uri_as_string(statement->subject->value.uri);
		}
	}
	return data;
}


std::string raptor_statement_get_predicate(const raptor_statement* statement){
	std::string data;
	if (statement->predicate) {
		data+=(const char*) raptor_uri_as_string(statement->predicate->value.uri);
	} else {
		data+="NULL";
	}
	return data;
}
std::string raptor_statement_get_object(const raptor_statement* statement){
	std::string data;
	if (statement->object) {
		if (statement->object->type == RAPTOR_TERM_TYPE_LITERAL) {
			if (statement->object->value.literal.datatype) {
				raptor_uri* dt_uri = statement->object->value.literal.datatype;
				data +=" <";
				data +=(const char*) raptor_uri_as_string(dt_uri);
				data +="> ";
			}
			data+="\"";
			data+=(const char*) statement->object->value.literal.string;
			data+="\"";
		} else if (statement->object->type == RAPTOR_TERM_TYPE_BLANK){
			data+=(const char*) statement->object->value.blank.string;
		}
		else {
			data+=(const char*) raptor_uri_as_string(statement->object->value.uri);
		}
	} else {
		data+=" NULL ";
	}
	return data;
}
